6: Create Connection between Verifier and Holder

Again we first create a connection, this time between the Verifier and Holder. For this connection we use the Out Of Band (OOB) protocol to connect to a tenant that does not necessarily have a public DID.

Note: A verifier is not necessarily onboarded with a public DID - only if they have an issuer role too - so they can only set use_public_did to true if they have configured it themselves.

curl -X 'POST' \
  'http://cloudapi.127.0.0.1.nip.io/tenant/v1/oob/create-invitation' \
  -H 'Content-Type: application/json' \
  -H 'X-Api-Key: tenant.<Verifier token>' \
  -d '{
  "alias": "Verifier<>Holder",
  "multi_use": false,
  "use_public_did": false,
  "create_connection": true
}'

Response:

{
  "created_at": null,
  "invi_msg_id": "754dfe3b-2a08-4863-bfaf-6af7b1e44c99",
  "invitation": {
    "@id": "754dfe3b-2a08-4863-bfaf-6af7b1e44c99",
    "@type": "https://didcomm.org/out-of-band/1.1/invitation",
    "accept": null,
    "goal": null,
    "goal_code": null,
    "handshake_protocols": [
      "https://didcomm.org/didexchange/1.0",
      "https://didcomm.org/connections/1.0"
    ],
    "imageUrl": "https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png",
    "label": "FaberIssuer",
    "requests~attach": null,
    "services": [
      {
        "id": "#inline",
        "type": "did-communication",
        "recipientKeys": [
          "did:key:z6MkjtuC76aqXhKQPekfT51GrtURJW8gZPXrGJi8huG6SkNx#z6MkjtuC76aqXhKQPekfT51GrtURJW8gZPXrGJi8huG6SkNx"
        ],
        "serviceEndpoint": "http://multitenant-agent:3020"
      }
    ]
  },
  "invitation_id": null,
  "invitation_url": "http://multitenant-agent:3020?oob=eyJAdHlwZSI6ICJodHRwczovL2RpZGNvbW0ub3JnL291dC1vZi1iYW5kLzEuMS9pbnZpdGF0aW9uIiwgIkBpZCI6ICI3NTRkZmUzYi0yYTA4LTQ4NjMtYmZhZi02YWY3YjFlNDRjOTkiLCAibGFiZWwiOiAiRmFiZXJJc3N1ZXIiLCAiaW1hZ2VVcmwiOiAiaHR0cHM6Ly91cGxvYWQud2lraW1lZGlhLm9yZy93aWtpcGVkaWEvY29tbW9ucy83LzcwL0V4YW1wbGUucG5nIiwgImhhbmRzaGFrZV9wcm90b2NvbHMiOiBbImh0dHBzOi8vZGlkY29tbS5vcmcvZGlkZXhjaGFuZ2UvMS4wIiwgImh0dHBzOi8vZGlkY29tbS5vcmcvY29ubmVjdGlvbnMvMS4wIl0sICJzZXJ2aWNlcyI6IFt7ImlkIjogIiNpbmxpbmUiLCAidHlwZSI6ICJkaWQtY29tbXVuaWNhdGlvbiIsICJyZWNpcGllbnRLZXlzIjogWyJkaWQ6a2V5Ono2TWtqdHVDNzZhcVhoS1FQZWtmVDUxR3J0VVJKVzhnWlBYckdKaThodUc2U2tOeCN6Nk1ranR1Qzc2YXFYaEtRUGVrZlQ1MUdydFVSSlc4Z1pQWHJHSmk4aHVHNlNrTngiXSwgInNlcnZpY2VFbmRwb2ludCI6ICJodHRwOi8vbXVsdGl0ZW5hbnQtYWdlbnQ6MzAyMCJ9XX0",
  "oob_id": "12b5be90-b8fc-40a8-9568-af85b7b31c9b",
  "state": "initial",
  "trace": false,
  "updated_at": null
}

The Holder accepts the invitation using the invitation object shown above. Alternatively, the invitation can be decoded from the base64 payload in the invitation_url field, found after the oob= parameter:

curl -X 'POST' \
  'http://cloudapi.127.0.0.1.nip.io/tenant/v1/oob/accept-invitation' \
  -H 'Content-Type: application/json' \
  -H 'X-Api-Key: tenant.<Holder token>' \
  -d '{
  "alias": "Alice<>Verifier",
  "use_existing_connection": true,
  "invitation": {
    "@id": "754dfe3b-2a08-4863-bfaf-6af7b1e44c99",
    "@type": "https://didcomm.org/out-of-band/1.1/invitation",
    "accept": null,
    "goal": null,
    "goal_code": null,
    "handshake_protocols": [
      "https://didcomm.org/didexchange/1.0",
      "https://didcomm.org/connections/1.0"
    ],
    "imageUrl": "https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png",
    "label": "FaberIssuer",
    "requests~attach": null,
    "services": [
      {
        "id": "#inline",
        "type": "did-communication",
        "recipientKeys": [
          "did:key:z6MkjtuC76aqXhKQPekfT51GrtURJW8gZPXrGJi8huG6SkNx#z6MkjtuC76aqXhKQPekfT51GrtURJW8gZPXrGJi8huG6SkNx"
        ],
        "serviceEndpoint": "http://multitenant-agent:3020"
      }
    ]
  }
}'

Response:

{
  "attach_thread_id": null,
  "connection_id": "c750b292-8d3e-467e-8e92-f0ecf19ee97e",
  "created_at": "2025-01-15T06:21:25.555579Z",
  "invi_msg_id": "754dfe3b-2a08-4863-bfaf-6af7b1e44c99",
  "invitation": {
    "@id": "754dfe3b-2a08-4863-bfaf-6af7b1e44c99",
    "@type": "https://didcomm.org/out-of-band/1.1/invitation",
    "accept": null,
    "goal": null,
    "goal_code": null,
    "handshake_protocols": [
      "https://didcomm.org/didexchange/1.0",
      "https://didcomm.org/connections/1.0"
    ],
    "imageUrl": "https://upload.wikimedia.org/wikipedia/commons/7/70/Example.png",
    "label": "FaberIssuer",
    "requests~attach": null,
    "services": [
      {
        "id": "#inline",
        "type": "did-communication",
        "recipientKeys": [
          "did:key:z6MkjtuC76aqXhKQPekfT51GrtURJW8gZPXrGJi8huG6SkNx#z6MkjtuC76aqXhKQPekfT51GrtURJW8gZPXrGJi8huG6SkNx"
        ],
        "serviceEndpoint": "http://multitenant-agent:3020"
      }
    ]
  },
  "multi_use": false,
  "oob_id": "b2ae7b58-4ce2-4ee8-81cd-3bba30c6cc8f",
  "our_recipient_key": null,
  "role": "receiver",
  "state": "deleted",
  "their_service": null,
  "trace": false,
  "updated_at": "2025-01-15T06:21:25.555579Z"
}

Listen to Webhooks until this connection is in state: completed.

{
  "wallet_id": "7bb24cc8-2e56-4326-9020-7870ad67b257",
  "topic": "connections",
  "origin": "multitenant",
  "payload": {
    "alias": "Holder <> Verifier",
    "connection_id": "bc8f43aa-5c02-401d-86a0-45d6d08f94b8",
    "connection_protocol": "connections/1.0",
    "created_at": "2025-01-20T10:06:01.683789Z",
    "error_msg": null,
    "invitation_key": "Cn3rHufXa94xCUKoSGseXinFSn6oNBb543n15NE6mLzJ",
    "invitation_mode": "once",
    "invitation_msg_id": "4a68ed4b-6a86-45e2-95e9-a76edcd93bc4",
    "my_did": "CnjLLG4U5RPbrYHG4cTMWw",
    "state": "completed",
    "their_did": "2guow2rkGp9wESxZPEWPSJ",
    "their_label": "Demo Verifier",
    "their_public_did": null,
    "their_role": "inviter",
    "updated_at": "2025-01-20T10:06:01.922033Z"
  }
}

Next: Verify Issued Credential